package com.futvan.z.framework.core;

import com.alibaba.fastjson.JSONObject;
import com.futvan.z.framework.common.bean.Result;
import com.futvan.z.framework.util.DateUtil;
import com.futvan.z.framework.util.JsonUtil;
import com.futvan.z.framework.util.StringUtil;
import com.futvan.z.system.user_channels.z_user_channels;
import com.futvan.z.system.zmessages.z_messages;
import com.futvan.z.system.zuser.z_user;
import io.netty.channel.*;
import io.netty.channel.group.ChannelGroup;
import io.netty.channel.group.DefaultChannelGroup;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import io.netty.util.concurrent.GlobalEventExecutor;

import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 消息处理类
 */
public class NettyWebSocketHandler extends SimpleChannelInboundHandler<TextWebSocketFrame> {
    protected static Map<String,Channel> channels = new ConcurrentHashMap<>(1024);//已连接的Channel key：channelid  value:channel对象

    protected static ChannelGroup system_group = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);//系统通知组

    /**
     * 消息处理
     * @param fromc_context
     * @param msg
     * @throws Exception
     */
    @Override
    public void channelRead0(ChannelHandlerContext fromc_context, TextWebSocketFrame msg) throws Exception {


        //发信人Channel
        Channel fromuser_channel = fromc_context.channel();

        //获取消息
        Result message_result = TextWebSocketFrameToZMessage(msg);

        //转换消息成功
        if(message_result.ifSuccess()){
            //获取消息
            z_messages messages = (z_messages) message_result.getData();
            z.Log("通讯消息："+ StringUtil.UrlDecode(JsonUtil.getJson(messages)));

            //用户上线
            if("user_on_line".equals(messages.getCommand_type())) {
                //保存发送人用户信息
                SaveUserChannel(messages,fromc_context);
                //加入系统群发组
                if(z.isNull(system_group.find(fromuser_channel.id()))){
                    system_group.add(fromuser_channel);
                }
                //发送系统通知
                SendSystemMessage(messages);
            }else if("user_off_line".equals(messages.getCommand_type())) {
                //用户下线，发送系统通知
                SendSystemMessage(messages);
                system_group.remove(fromuser_channel);
            }else if("usertouser".equals(messages.getCommand_type())) {
                //用户间发送信息
                SendMessage_usertouser(fromuser_channel,messages);
            }else if("system_message".equals(messages.getCommand_type())) {
                //系统通知
                SendMessage_system_message(fromuser_channel,messages);
            }else if("group_message".equals(messages.getCommand_type())) {
                //群发消息
                SendMessage_group_message(fromuser_channel,messages);
            }else if("e_message".equals(messages.getCommand_type())) {
                //异常信息发送
                SendMessage_e_message(fromuser_channel,messages);
            }else if("audio_apply".equals(messages.getCommand_type())) {
                //语音通话申请
                SendMessage_usertouser(fromuser_channel,messages);
            }else if("audio_close".equals(messages.getCommand_type())) {
                //结束语音通话
                SendMessage_usertouser(fromuser_channel,messages);
            }else if("audio_apply_yes".equals(messages.getCommand_type())) {
                //语音通话接受
                SendMessage_usertouser(fromuser_channel,messages);
            }else if("audio_apply_no".equals(messages.getCommand_type())) {
                //语音通话拒绝
                SendMessage_usertouser(fromuser_channel,messages);
            }else if("video_apply".equals(messages.getCommand_type())) {
                //视频通话申请
                SendMessage_usertouser(fromuser_channel,messages);
            }else if("video_close".equals(messages.getCommand_type())) {
                //结束视频通话
                SendMessage_usertouser(fromuser_channel,messages);
            }else if("video_apply_yes".equals(messages.getCommand_type())) {
                //视频通话接受
                SendMessage_usertouser(fromuser_channel,messages);
            }else if("video_apply_no".equals(messages.getCommand_type())) {
                //视频通话拒绝
                SendMessage_usertouser(fromuser_channel,messages);
            }else if("webrtc_candidate".equals(messages.getCommand_type())) {
                //协商信息
                SendMessage_usertouser(fromuser_channel,messages);
            }else if("webrtc_offer".equals(messages.getCommand_type())) {
                //协商信息
                SendMessage_usertouser(fromuser_channel,messages);
            }else if("webrtc_answer".equals(messages.getCommand_type())) {
                //协商信息
                SendMessage_usertouser(fromuser_channel,messages);
            }else {
                AsyncSendText(fromuser_channel,JsonUtil.getJson(Result.error("发送消息失败|通讯指令无效|",messages)));
            }
        }else{
            AsyncSendText(fromuser_channel,JsonUtil.getJson(Result.error(message_result.getMsg())));
        }
    }

    /**
     * 发送系统通知
     * @param messages
     */
    private void SendSystemMessage(z_messages messages) {
        system_group.writeAndFlush(new TextWebSocketFrame(JsonUtil.getJson(Result.success(messages))));
    }

    /**
     * 保存发送人用户信息
     * @param messages
     * @param fromcContext
     */
    private void SaveUserChannel(z_messages messages, ChannelHandlerContext fromcContext) {
        if(z.isNotNull(messages)){
            String fromuserid = messages.getFromuserid();
            String newUserChannelid = fromcContext.channel().id().asShortText();
            if(z.isNotNull(fromuserid)){
                z_user_channels uc = new z_user_channels();
                uc.setUserid(fromuserid);
                uc.setChannelid(newUserChannelid);
                List<z_user_channels> list = getUserChannels(uc);
                if(z.isNull(list) || (z.isNotNull(list) && list.size()<=0)){
                    //保存当前用户通道信息
                    z.getSqlSession().insert("insert","insert into z_user_channels(zid,userid,channelid,channels_active)values (uuid(),'"+fromuserid+"','"+newUserChannelid+"','"+fromcContext.channel().isActive()+"');");
                    channels.put(newUserChannelid,fromcContext.channel());
                }
            }
        }
    }

    /**
     * 获取用户通道列表信息
     * @param uc
     * @return
     */
    private List<z_user_channels> getUserChannels(z_user_channels uc){
        return z.getSqlSession().selectList("z_user_channels_select",uc);
    }


    private void SendMessage_usertouser(Channel fromuser_channel,z_messages msg) throws InterruptedException {
        //判读接收人不可为空
        if(z.isNotNull(msg) && z.isNotNull(msg.getTouserid())){

            //获取接收人通道
            z_user_channels uc = new z_user_channels();
            uc.setUserid(msg.getTouserid());
            List<z_user_channels> list = getUserChannels(uc);
            if(z.isNotNull(list) && list.size()>0){

                //遍历接收人所有通道，执行发送
                for (z_user_channels userChannel : list) {
                    if(z.isNotNull(userChannel.getChannelid())){
                        Channel ToUserChannel = channels.get(userChannel.getChannelid());
                        if(ToUserChannel.isActive()){
                            //执行发送
                            String msgjson = JsonUtil.getJson(Result.success(msg));
                            ChannelFuture channelFuture = ToUserChannel.writeAndFlush(new TextWebSocketFrame(msgjson));

                            //添加ChannelFuture监听方法，获取发送信息执行结果
                            channelFuture.addListener(new ChannelFutureListener() {
                                @Override
                                public void operationComplete(ChannelFuture channelFuture) throws Exception {
                                    //获取发送状态，并完成回传信息给发信人
                                    if(channelFuture.isSuccess()){
                                        AsyncSendText(fromuser_channel,JsonUtil.getJson(Result.success(msg)));
                                    }else{
                                        AsyncSendText(fromuser_channel,JsonUtil.getJson(Result.error("发送消息失败",msg)));
                                    }
                                }
                            });
                        }else{
                            z.getSqlSession().delete("delete","delete from z_user_channels where zid = '"+userChannel.getZid()+"'");
                        }
                    }
                }
            }else{
                AsyncSendText(fromuser_channel,JsonUtil.getJson(Result.error("发送消息失败|目标用户未在线",msg)));
            }
        }else{
            AsyncSendText(fromuser_channel,JsonUtil.getJson(Result.error("发送消息失败|z_messages无效",msg)));
        }
    }



    private void SendMessage_group_message(Channel fromuser_channel,z_messages msg) {
    }
    private void SendMessage_system_message(Channel fromuser_channel,z_messages msg) {
    }
    private void SendMessage_user_off_line(Channel fromuser_channel,z_messages msg) {
    }
    private void SendMessage_user_on_line(Channel fromuser_channel,z_messages msg) {
    }
    private void SendMessage_e_message(Channel fromuser_channel,z_messages msg) {
    }

    /**
     * TextWebSocketFrame中提取Json转z_messages
     * @param msg
     * @return
     */
    private Result TextWebSocketFrameToZMessage(TextWebSocketFrame msg) {
        Result result = new Result();
        try {
            z_messages messages = JSONObject.parseObject(msg.text(), z_messages.class);
            if(z.isNotNull(messages)) {
                if(z.isNull(messages.getCommand_type())) {
                    result.setError("无效通信数据|通信命令不可为空");
                }

                //if(z.isNull(z.code_detail.get("command_type_"+messages.getCommand_type()))){
                if(!"usertouser".equals(messages.getCommand_type()) &&
                        !"user_on_line".equals(messages.getCommand_type()) &&
                        !"user_off_line".equals(messages.getCommand_type()) &&
                        !"group_message".equals(messages.getCommand_type()) &&
                        !"voice_apply".equals(messages.getCommand_type()) &&
                        !"voice_apply_yes".equals(messages.getCommand_type()) &&
                        !"voice_apply_no".equals(messages.getCommand_type()) &&
                        !"video_apply".equals(messages.getCommand_type()) &&
                        !"video_apply_yes".equals(messages.getCommand_type()) &&
                        !"video_apply_no".equals(messages.getCommand_type()) &&
                        !"system_message".equals(messages.getCommand_type()) &&
                        !"system_error".equals(messages.getCommand_type())){
                    result.setError("无效通信数据|通信命令无效:"+messages.getCommand_type());
                }

                if(z.isNotNull(messages.getMsgtype())) {
                    //if(z.isNull(z.code_detail.get("msgtype_"+messages.getMsgtype()))) {
                    if(!"0".equals(messages.getMsgtype()) &&
                            !"1".equals(messages.getMsgtype()) &&
                            !"2".equals(messages.getMsgtype()) &&
                            !"3".equals(messages.getMsgtype()) &&
                            !"4".equals(messages.getMsgtype())){
                        result.setError("无效通信数据|消息类型无效："+messages.getMsgtype());
                    }
                }
                //未发现错误，设置返回值
                if(!result.ifError()){

                    //设置发送时间
                    if(z.isNull(messages.getSendtime())){
                        messages.setSendtime(DateUtil.getDateTime());
                    }

                    //设置接收人名称
                    if(z.isNull(messages.getTousername()) && z.isNotNull(messages.getTouserid())){
                        z_user touser = z.users_userid.get(messages.getTouserid());
                        if(z.isNotNull(touser)){
                            messages.setTousername(touser.getUser_name());
                        }else{
                            messages.setTousername(messages.getTouserid());
                        }
                    }

                    //设置发送人名称
                    if(z.isNull(messages.getFromusername()) && z.isNotNull(messages.getFromuserid())){
                        z_user fromuser = z.users_userid.get(messages.getFromuserid());
                        if(z.isNotNull(fromuser)){
                            messages.setFromusername(fromuser.getUser_name());
                        }else{
                            messages.setFromusername(messages.getFromuserid());
                        }
                    }

                    //返回
                    result.setSuccess(messages);
                }
            }else{
                result.setError("无效通信数据|" + msg.text());
            }
        } catch (Exception e) {
            result.setError("无效通信数据|"+msg.text());
        }
        return result;
    }

    /**
     * 建立连接
     * @param ctx
     * @throws Exception
     */
    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        z.Log("WebSocket建立连接："+ctx.channel());
    }

    /**
     * 关闭连接
     * @param ctx
     * @throws Exception
     */
    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        // 断开连接
        z.Log("WebSocket连接关闭："+ctx.channel());
    }

    /**
     * 异常处理
     * @param ctx
     * @param cause
     * @throws Exception
     */
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        // 异常处理
        cause.printStackTrace();
        ctx.close();
    }

    /**
     * 异步发送文本信息
     * @param channel
     * @param msg
     */
    private void AsyncSendText(Channel channel,String msg){
        if(z.isNotNull(channel) && channel.isActive()){
            channel.writeAndFlush(new TextWebSocketFrame(msg));
        }
    }

}
